/**
 * @file car_pid.h
 * @author circleup (circleup@foxmail.com)
 * @brief PID 控制函数
 * @version 2.7
 * @date 2020-07-08
 * 
 * @copyright Copyright (c) 2020
 * 
 */


#ifndef __PID_H
#define __PID_H	  

///< PID输出范围宏定义
#define DEFAULT_PID_OUT_MAX               ( 300)
#define DEFAULT_PID_OUT_MIN               ( -300)

///< PID积分范围宏定义
#define DEFAULT_PID_INTEGRAL_OUT_MAX      ( 10000)
#define DEFAULT_PID_INTEGRAL_OUT_MIN      (-10000)

///< PID变量类型宏定义
#define PID_VAR_TYPE                      double

/**
 * @brief PID 参数结构体
 * 
 */
typedef struct  
{  
    PID_VAR_TYPE SetPoint;      ///< 设定目标 
    PID_VAR_TYPE Proportion;    ///< 比例常数
    PID_VAR_TYPE Integral;      ///< 积分常数
    PID_VAR_TYPE Derivative;    ///< 微分常数 
    PID_VAR_TYPE SumError;      ///< 积分和
    PID_VAR_TYPE Error;         ///< 误差
    PID_VAR_TYPE LastError;     ///< 上次误差 
    PID_VAR_TYPE PrevError;     ///< 前一次误差   
    PID_VAR_TYPE LastResult;    ///< 上次计算结果
    PID_VAR_TYPE Result;        ///< 当前计算结果
    PID_VAR_TYPE OutMax;        ///< 输出限幅最大值
    PID_VAR_TYPE OutMin;        ///< 输出限幅最小值
    PID_VAR_TYPE IntegralMax;   ///< 积分限幅最大值
    PID_VAR_TYPE IntegralMin;   ///< 积分限幅最小值
}PID;

/**
 * @brief 转向 PID 结构体
 * 
 */
extern PID turn_PID;

/**
 * @brief 速度 PID 结构体
 * 
 */
extern PID motor_PID;

/**
 * @brief PID初始化
 * 
 * @param s_PID   PID 结构体指针
 * @param set_point 初始设定值
 * @param Proportion 比例
 * @param Integral 积分
 * @param Derivative 微分
 */
void PID_Init(PID * s_PID, PID_VAR_TYPE set_point,PID_VAR_TYPE Proportion, PID_VAR_TYPE Integral, PID_VAR_TYPE Derivative);

/**
 * @brief 设置PID输出范围
 * 
 * @param s_PID PID 结构体指针
 * @param outMax 输出上限
 * @param outMin 输出下限
 */
void  PID_SetOutRange  (PID * s_PID, PID_VAR_TYPE outMax,PID_VAR_TYPE outMin);

/**
 * @brief 设置PID积分范围
 * 
 * @param s_PID PID 结构体指针
 * @param IntegralMax 积分上限
 * @param IntegralMin 积分下限
 */
void  PID_SetIntegralOutRange(PID * s_PID, PID_VAR_TYPE IntegralMax,PID_VAR_TYPE IntegralMin);

/**
 * @brief 设置目标值
 * 
 * @param s_PID PID 结构体指针
 * @param set_point 目标值
 */
void  PID_SetPoint     (PID * s_PID, PID_VAR_TYPE set_point);

/**
 * @brief 增量式PID计算
 * 
 * @param s_PID 
 * @param now_point 当前值
 * @return PID_VAR_TYPE 给定输出增量
 */
PID_VAR_TYPE Increment_PID_Cal(PID * s_PID, PID_VAR_TYPE now_point);

/**
 * @brief 位置式PID计算
 * 
 * @param s_PID PID 结构体指针
 * @param now_point  当前值
 * @return PID_VAR_TYPE 给定输出
 */
PID_VAR_TYPE Position_PID_Cal(PID * s_PID, PID_VAR_TYPE now_point);

#endif 
